mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2025-07-28 04:33:42 +08:00
[offers][fix] tweak hero (#445)
* [portal][ui] increase font size of global elements * [offers] tweak hero * change some sizes * tweak again
This commit is contained in:
@ -33,7 +33,7 @@ function ProfileJewel() {
|
|||||||
if (session == null) {
|
if (session == null) {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
className="text-sm font-medium"
|
className="text-base"
|
||||||
href="/api/auth/signin"
|
href="/api/auth/signin"
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -169,7 +169,6 @@ export default function AppShell({ children }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Mobile menu */}
|
{/* Mobile menu */}
|
||||||
<MobileNavigation
|
<MobileNavigation
|
||||||
globalNavigationItems={GlobalNavigation}
|
globalNavigationItems={GlobalNavigation}
|
||||||
@ -178,7 +177,6 @@ export default function AppShell({ children }: Props) {
|
|||||||
productTitle={currentProductNavigation.title}
|
productTitle={currentProductNavigation.title}
|
||||||
setIsShown={setMobileMenuOpen}
|
setIsShown={setMobileMenuOpen}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Content area */}
|
{/* Content area */}
|
||||||
<div className="flex h-screen flex-1 flex-col overflow-hidden">
|
<div className="flex h-screen flex-1 flex-col overflow-hidden">
|
||||||
<header className="w-full">
|
<header className="w-full">
|
||||||
|
@ -27,10 +27,14 @@ export default function ProductNavigation({ items, title, titleHref }: Props) {
|
|||||||
return (
|
return (
|
||||||
<nav aria-label="Global" className="flex h-full items-center space-x-8">
|
<nav aria-label="Global" className="flex h-full items-center space-x-8">
|
||||||
<Link
|
<Link
|
||||||
className="hover:text-primary-700 flex items-center gap-2 text-sm font-medium"
|
className="hover:text-primary-700 flex items-center gap-2 text-base font-medium"
|
||||||
href={titleHref}>
|
href={titleHref}>
|
||||||
{titleHref !== '/' && (
|
{titleHref !== '/' && (
|
||||||
<img alt="TIH" className="h-8 w-auto" src="/logo.svg" />
|
<img
|
||||||
|
alt="Tech Interview Handbook"
|
||||||
|
className="h-8 w-auto"
|
||||||
|
src="/logo.svg"
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{title}
|
{title}
|
||||||
</Link>
|
</Link>
|
||||||
@ -39,7 +43,7 @@ export default function ProductNavigation({ items, title, titleHref }: Props) {
|
|||||||
const isActive = router.pathname === item.href;
|
const isActive = router.pathname === item.href;
|
||||||
return item.children != null && item.children.length > 0 ? (
|
return item.children != null && item.children.length > 0 ? (
|
||||||
<Menu key={item.name} as="div" className="relative text-left">
|
<Menu key={item.name} as="div" className="relative text-left">
|
||||||
<Menu.Button className="focus:ring-primary-600 flex items-center rounded-md text-sm font-medium text-slate-900 focus:outline-none focus:ring-2 focus:ring-offset-2">
|
<Menu.Button className="focus:ring-primary-600 flex items-center rounded-md text-base font-medium text-slate-900 focus:outline-none focus:ring-2 focus:ring-offset-2">
|
||||||
<span>{item.name}</span>
|
<span>{item.name}</span>
|
||||||
<ChevronDownIcon
|
<ChevronDownIcon
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@ -62,7 +66,7 @@ export default function ProductNavigation({ items, title, titleHref }: Props) {
|
|||||||
<Link
|
<Link
|
||||||
className={clsx(
|
className={clsx(
|
||||||
active ? 'bg-slate-100' : '',
|
active ? 'bg-slate-100' : '',
|
||||||
'block px-4 py-2 text-sm text-slate-700',
|
'block px-4 py-2 text-base text-slate-700',
|
||||||
)}
|
)}
|
||||||
href={child.href}
|
href={child.href}
|
||||||
rel={
|
rel={
|
||||||
@ -84,7 +88,7 @@ export default function ProductNavigation({ items, title, titleHref }: Props) {
|
|||||||
<Link
|
<Link
|
||||||
key={item.name}
|
key={item.name}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'hover:text-primary-600 inline-flex h-full items-center border-y-2 border-t-transparent text-sm text-slate-900',
|
'hover:text-primary-600 inline-flex h-full items-center border-y-2 border-t-transparent text-base text-slate-900',
|
||||||
isActive ? 'border-b-primary-500' : 'border-b-transparent',
|
isActive ? 'border-b-primary-500' : 'border-b-transparent',
|
||||||
)}
|
)}
|
||||||
href={item.href}
|
href={item.href}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import type { ProductNavigationItems } from '~/components/global/ProductNavigation';
|
import type { ProductNavigationItems } from '~/components/global/ProductNavigation';
|
||||||
|
|
||||||
const navigation: ProductNavigationItems = [
|
const navigation: ProductNavigationItems = [
|
||||||
{ href: '/offers/browse', name: 'Browse' },
|
{ href: '/offers/browse', name: 'Browse all offers' },
|
||||||
{ href: '/offers/submit', name: 'Analyse your offers' },
|
{ href: '/offers/submit', name: 'Analyze your offers' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
@ -10,7 +10,7 @@ const config = {
|
|||||||
googleAnalyticsMeasurementID: 'G-DBLZDQ2ZZN',
|
googleAnalyticsMeasurementID: 'G-DBLZDQ2ZZN',
|
||||||
navigation,
|
navigation,
|
||||||
showGlobalNav: false,
|
showGlobalNav: false,
|
||||||
title: 'Offer Profile Repository',
|
title: 'Tech Offers Repo',
|
||||||
titleHref: '/offers',
|
titleHref: '/offers',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
export default function OffersTitle() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="flex items-end justify-center">
|
|
||||||
<h1 className="text-primary-600 mt-16 text-center text-4xl font-bold">
|
|
||||||
Offer Profile Repository
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div className="text-primary-500 mt-2 text-center text-2xl font-normal">
|
|
||||||
Reveal profile stories behind offers
|
|
||||||
</div>
|
|
||||||
<div className="items-top flex justify-center text-xl font-normal">
|
|
||||||
Click into offers to view profiles, benchmark your offers and profiles,
|
|
||||||
and discuss with the community
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,3 +1,4 @@
|
|||||||
|
import clsx from 'clsx';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
import type { JobTitleType } from '~/components/shared/JobTitles';
|
import type { JobTitleType } from '~/components/shared/JobTitles';
|
||||||
@ -14,12 +15,8 @@ export default function OfferTableRow({
|
|||||||
row: { company, id, income, monthYearReceived, profileId, title, totalYoe },
|
row: { company, id, income, monthYearReceived, profileId, title, totalYoe },
|
||||||
}: OfferTableRowProps) {
|
}: OfferTableRowProps) {
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr key={id} className="divide-x divide-slate-200 border-b bg-white">
|
||||||
key={id}
|
<th className="whitespace-nowrap py-4 px-6 font-medium" scope="row">
|
||||||
className="border-b bg-white hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-800 dark:hover:bg-slate-600">
|
|
||||||
<th
|
|
||||||
className="whitespace-nowrap py-4 px-6 font-medium text-slate-900 dark:text-white"
|
|
||||||
scope="row">
|
|
||||||
{company.name}
|
{company.name}
|
||||||
</th>
|
</th>
|
||||||
<td className="py-4 px-6">
|
<td className="py-4 px-6">
|
||||||
@ -28,7 +25,10 @@ export default function OfferTableRow({
|
|||||||
<td className="py-4 px-6">{totalYoe}</td>
|
<td className="py-4 px-6">{totalYoe}</td>
|
||||||
<td className="py-4 px-6">{convertMoneyToString(income)}</td>
|
<td className="py-4 px-6">{convertMoneyToString(income)}</td>
|
||||||
<td className="py-4 px-6">{formatDate(monthYearReceived)}</td>
|
<td className="py-4 px-6">{formatDate(monthYearReceived)}</td>
|
||||||
<td className="space-x-4 py-4 px-6">
|
<td
|
||||||
|
className={clsx(
|
||||||
|
'sticky right-0 bg-white py-4 px-6 drop-shadow md:drop-shadow-none',
|
||||||
|
)}>
|
||||||
<Link
|
<Link
|
||||||
className="text-primary-600 dark:text-primary-500 font-medium hover:underline"
|
className="text-primary-600 dark:text-primary-500 font-medium hover:underline"
|
||||||
href={`/offers/profile/${profileId}`}>
|
href={`/offers/profile/${profileId}`}>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
import clsx from 'clsx';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { HorizontalDivider, Select, Spinner, Tabs } from '@tih/ui';
|
import { DropdownMenu, Spinner } from '@tih/ui';
|
||||||
|
|
||||||
import OffersTablePagination from '~/components/offers/table/OffersTablePagination';
|
import OffersTablePagination from '~/components/offers/table/OffersTablePagination';
|
||||||
import {
|
import {
|
||||||
@ -71,55 +72,84 @@ export default function OffersTable({
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
function renderTabs() {
|
|
||||||
return (
|
|
||||||
<div className="flex justify-center">
|
|
||||||
<div className="w-fit">
|
|
||||||
<Tabs
|
|
||||||
label="Table Navigation"
|
|
||||||
tabs={OfferTableTabOptions}
|
|
||||||
value={selectedTab}
|
|
||||||
onChange={(value) => setSelectedTab(value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderFilters() {
|
function renderFilters() {
|
||||||
return (
|
return (
|
||||||
<div className="m-4 flex items-center justify-between">
|
<div className="m-4 flex items-center justify-between">
|
||||||
<div className="justify-left flex items-center space-x-2">
|
<DropdownMenu
|
||||||
<span>All offers in</span>
|
align="start"
|
||||||
<CurrencySelector
|
label={
|
||||||
handleCurrencyChange={(value: string) => setCurrency(value)}
|
OfferTableTabOptions.filter(
|
||||||
selectedCurrency={currency}
|
({ value: itemValue }) => itemValue === selectedTab,
|
||||||
/>
|
)[0].label
|
||||||
|
}
|
||||||
|
size="inherit">
|
||||||
|
{OfferTableTabOptions.map(({ label: itemLabel, value }) => (
|
||||||
|
<DropdownMenu.Item
|
||||||
|
key={value}
|
||||||
|
isSelected={value === selectedTab}
|
||||||
|
label={itemLabel}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedTab(value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</DropdownMenu>
|
||||||
|
<div className="divide-x-slate-200 flex items-center space-x-4 divide-x">
|
||||||
|
<div className="justify-left flex items-center space-x-2">
|
||||||
|
<span>All offers in</span>
|
||||||
|
<CurrencySelector
|
||||||
|
handleCurrencyChange={(value: string) => setCurrency(value)}
|
||||||
|
selectedCurrency={currency}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="pl-4">
|
||||||
|
<DropdownMenu
|
||||||
|
align="end"
|
||||||
|
label={
|
||||||
|
OfferTableFilterOptions.filter(
|
||||||
|
({ value: itemValue }) => itemValue === selectedFilter,
|
||||||
|
)[0].label
|
||||||
|
}
|
||||||
|
size="inherit">
|
||||||
|
{OfferTableFilterOptions.map(({ label: itemLabel, value }) => (
|
||||||
|
<DropdownMenu.Item
|
||||||
|
key={value}
|
||||||
|
isSelected={value === selectedFilter}
|
||||||
|
label={itemLabel}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedFilter(value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Select
|
|
||||||
isLabelHidden={true}
|
|
||||||
label=""
|
|
||||||
options={OfferTableFilterOptions}
|
|
||||||
value={selectedFilter}
|
|
||||||
onChange={(value) => setSelectedFilter(value)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderHeader() {
|
function renderHeader() {
|
||||||
|
const columns = [
|
||||||
|
'Company',
|
||||||
|
'Title',
|
||||||
|
'YOE',
|
||||||
|
selectedTab === YOE_CATEGORY.INTERN ? 'Monthly Salary' : 'Annual TC',
|
||||||
|
'Date Offered',
|
||||||
|
'Actions',
|
||||||
|
];
|
||||||
return (
|
return (
|
||||||
<thead className="bg-slate-50 text-xs uppercase text-slate-700">
|
<thead className="text-slate-700">
|
||||||
<tr>
|
<tr className="divide-x divide-slate-200">
|
||||||
{[
|
{columns.map((header, index) => (
|
||||||
'Company',
|
<th
|
||||||
'Title',
|
key={header}
|
||||||
'YOE',
|
className={clsx(
|
||||||
selectedTab === YOE_CATEGORY.INTERN ? 'Monthly Salary' : 'TC/year',
|
'bg-slate-100 py-3 px-6',
|
||||||
'Date offered',
|
// Make last column sticky.
|
||||||
'Actions',
|
index === columns.length - 1 &&
|
||||||
].map((header) => (
|
'sticky right-0 drop-shadow md:drop-shadow-none',
|
||||||
<th key={header} className="py-3 px-6" scope="col">
|
)}
|
||||||
|
scope="col">
|
||||||
{header}
|
{header}
|
||||||
</th>
|
</th>
|
||||||
))}
|
))}
|
||||||
@ -136,23 +166,23 @@ export default function OffersTable({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-5/6">
|
<div className="w-5/6">
|
||||||
{renderTabs()}
|
<div className="relative w-full border border-slate-200">
|
||||||
<HorizontalDivider />
|
|
||||||
<div className="relative w-full overflow-x-auto shadow-md sm:rounded-lg">
|
|
||||||
{renderFilters()}
|
{renderFilters()}
|
||||||
{offersQuery.isLoading ? (
|
{offersQuery.isLoading ? (
|
||||||
<div className="col-span-10 pt-4">
|
<div className="col-span-10 pt-4">
|
||||||
<Spinner display="block" size="lg" />
|
<Spinner display="block" size="lg" />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<table className="w-full text-left text-sm text-slate-500">
|
<div className="overflow-x-auto">
|
||||||
{renderHeader()}
|
<table className="w-full divide-y divide-slate-200 border-y border-slate-200 text-left text-slate-600">
|
||||||
<tbody>
|
{renderHeader()}
|
||||||
{offers.map((offer) => (
|
<tbody>
|
||||||
<OffersRow key={offer.id} row={offer} />
|
{offers.map((offer) => (
|
||||||
))}
|
<OffersRow key={offer.id} row={offer} />
|
||||||
</tbody>
|
))}
|
||||||
</table>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
<OffersTablePagination
|
<OffersTablePagination
|
||||||
endNumber={
|
endNumber={
|
||||||
|
@ -45,6 +45,7 @@ export default function CompaniesTypeahead({
|
|||||||
}
|
}
|
||||||
placeholder={placeHolder}
|
placeholder={placeHolder}
|
||||||
required={required}
|
required={required}
|
||||||
|
textSize="inherit"
|
||||||
onQueryChange={setQuery}
|
onQueryChange={setQuery}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
/>
|
/>
|
||||||
|
@ -41,6 +41,7 @@ export default function JobTitlesTypeahead({
|
|||||||
options={options}
|
options={options}
|
||||||
placeholder={placeHolder}
|
placeholder={placeHolder}
|
||||||
required={required}
|
required={required}
|
||||||
|
textSize="inherit"
|
||||||
onQueryChange={setQuery}
|
onQueryChange={setQuery}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
/>
|
/>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { Banner } from '@tih/ui';
|
||||||
|
|
||||||
import OffersTitle from '~/components/offers/OffersTitle';
|
|
||||||
import OffersTable from '~/components/offers/table/OffersTable';
|
import OffersTable from '~/components/offers/table/OffersTable';
|
||||||
import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead';
|
import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead';
|
||||||
import JobTitlesTypeahead from '~/components/shared/JobTitlesTypahead';
|
import JobTitlesTypeahead from '~/components/shared/JobTitlesTypahead';
|
||||||
@ -11,26 +12,39 @@ export default function OffersHomePage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="flex-1 overflow-y-auto">
|
<main className="flex-1 overflow-y-auto">
|
||||||
<div className="grid-rows grid h-1/2 bg-slate-100">
|
<Banner size="sm">
|
||||||
<OffersTitle />
|
⭐ Check if your offer is competitive by submitting it{' '}
|
||||||
<div className="flex items-start justify-center">
|
<Link className="underline" href="/offers/submit">
|
||||||
<div className="mt-4 flex items-center">
|
here
|
||||||
Viewing offers for
|
</Link>
|
||||||
<div className="mx-4">
|
. ⭐
|
||||||
<JobTitlesTypeahead
|
</Banner>
|
||||||
isLabelHidden={true}
|
<div className="bg-slate-100 py-16 px-4">
|
||||||
placeHolder="Software Engineer"
|
<div>
|
||||||
onSelect={({ value }) => setjobTitleFilter(value)}
|
<div>
|
||||||
/>
|
<h1 className="text-primary-600 text-center text-4xl font-bold sm:text-5xl">
|
||||||
</div>
|
Tech Offers Repo
|
||||||
in
|
</h1>
|
||||||
<div className="ml-4">
|
</div>
|
||||||
<CompaniesTypeahead
|
<div className="mt-4 text-center text-lg text-slate-600 sm:text-2xl">
|
||||||
isLabelHidden={true}
|
Find out how good your offer is. Discover how others got their
|
||||||
placeHolder="All Companies"
|
offers.
|
||||||
onSelect={({ value }) => setCompanyFilter(value)}
|
</div>
|
||||||
/>
|
</div>
|
||||||
</div>
|
<div className="mt-6 flex flex-col items-center justify-center space-y-2 text-base text-slate-700 sm:mt-10 sm:flex-row sm:space-y-0 sm:space-x-4 sm:text-lg">
|
||||||
|
<span>Viewing offers for</span>
|
||||||
|
<div className="flex items-center space-x-4">
|
||||||
|
<JobTitlesTypeahead
|
||||||
|
isLabelHidden={true}
|
||||||
|
placeHolder="Software Engineer"
|
||||||
|
onSelect={({ value }) => setjobTitleFilter(value)}
|
||||||
|
/>
|
||||||
|
<span>in</span>
|
||||||
|
<CompaniesTypeahead
|
||||||
|
isLabelHidden={true}
|
||||||
|
placeHolder="All Companies"
|
||||||
|
onSelect={({ value }) => setCompanyFilter(value)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -96,7 +96,7 @@ export default function LandingPage() {
|
|||||||
<div className="mx-auto mt-10 max-w-sm sm:flex sm:max-w-none sm:justify-center">
|
<div className="mx-auto mt-10 max-w-sm sm:flex sm:max-w-none sm:justify-center">
|
||||||
<div className="space-y-4 sm:mx-auto sm:inline-grid sm:grid-cols-2 sm:gap-5 sm:space-y-0">
|
<div className="space-y-4 sm:mx-auto sm:inline-grid sm:grid-cols-2 sm:gap-5 sm:space-y-0">
|
||||||
<a
|
<a
|
||||||
className="border-grey-600 flex items-center justify-center rounded-md border bg-white bg-white px-4 py-3 text-base font-medium text-indigo-700 shadow-sm hover:bg-indigo-50 sm:px-8"
|
className="border-grey-600 flex items-center justify-center rounded-md border bg-white px-4 py-3 text-base font-medium text-indigo-700 shadow-sm hover:bg-indigo-50 sm:px-8"
|
||||||
href={HOME_URL}>
|
href={HOME_URL}>
|
||||||
Get started
|
Get started
|
||||||
</a>
|
</a>
|
||||||
|
Reference in New Issue
Block a user